package net.sf.odinms.exttools.doclet.pages;

import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import com.sun.javadoc.ClassDoc;
import com.sun.tools.doclets.internal.toolkit.util.Util;
import net.sf.odinms.exttools.doclet.AbstractPageWriter;
import net.sf.odinms.exttools.doclet.Doclet;

/**
 * Create "allclasses-[no]frame.html", with and without frame targets.
 * 
 * <p>
 * {@link com.sun.tools.doclets.formats.html.AllClassesFrameWriter} (part of the
 * Standard doclet) generates these files using an
 * {@link com.sun.tools.doclets.internal.toolkit.util.IndexBuilder} which
 * already has a sorted list of all documented symbols. However, there is
 * overhead in iterating through every symbol and only printing core classes,
 * whereas {@link com.sun.javadoc.RootDoc#classes()} returns only the classes
 * and interfaces for included packages.
 * </p>
 */
public final class AllClasses extends AbstractPageWriter {
	
	/** A set of all the classes, interfaces, etc. to be documented. */
	private static Set<ClassDoc> includedClasses;
	
	/** Create the frame at left containing all classes, interfaces, etc. */
	public static void generateAllClasses() {
		ClassDoc[] classes = CONF.root.classes();
		// A TreeSet will always be initialized in sorted order from an array.
		includedClasses = new TreeSet<ClassDoc>(Arrays.asList(classes));
		String filename = null;
		try {
			filename = "allclasses-frame" + CONF.ext;
			new AllClasses(filename, true);
			filename = "allclasses-noframe" + CONF.ext;
			new AllClasses(filename, false);
		}
		catch (IOException exc) {
			throw Doclet.exception(exc, filename);
		}
		
	}
	
	/**
	 * Initialize the filename and page type for the All Classes page.
	 * 
	 * @param filename The desired name of the file (with extension).
	 * @param includeFrameTargets True if "target" attributes should be added to
	 *        the link tags.
	 * @throws IOException If {@link java.io.FileOutputStream} creation fails.
	 */
	private AllClasses(String filename, boolean includeFrameTargets)
			throws IOException {
		super(filename);
		pageType = PageType.ALL_CLASSES;
		
		windowTitle = "All Classes";
		printXhtmlHeader(null, false);
		println(new TagBuilder("h3").getOpenTextClose("All Classes"));
		
		TagBuilder linkTag =
				new TagBuilder("a").add("target", (includeFrameTargets)
						? "classFrame"
						: null);
		for (ClassDoc cd : includedClasses) {
			// Only prints outer classes and static inner classes.
			if (Util.isCoreClass(cd)) {
				// Reuse the same TagBuilder for simplicity (overwrite args)
				linkTag.add("href", hrefToDoc(cd));
				linkTag.add("class", visibilityModifier(cd)
						+ classFlavor(cd, true));
				linkTag.add("title", classFlavor(cd, false) + " in "
						+ cd.containingPackage().name());
				println(linkTag.getOpenTextClose(cd.name()) + empty("br"));
			}
		}
		printXhtmlFooter();
		this.close();
	}
	
}
